#include <stdio.h>

#ifndef size_t
typedef unsigned long size_t;
#endif
/**
 * ARRAY_SIZE - get the number of elements in array @arr
 * @arr: array to be sized
 */
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))

#define offsetof(TYPE, MEMBER)	((size_t)&((TYPE *)0)->MEMBER)

/**
 * sizeof_field(TYPE, MEMBER)
 *
 * @TYPE: The structure containing the field of interest
 * @MEMBER: The field to return the size of
 */
#define sizeof_field(TYPE, MEMBER) sizeof((((TYPE *)0)->MEMBER))

/**
 * offsetofend(TYPE, MEMBER)
 *
 * @TYPE: The type of the structure
 * @MEMBER: The member within the structure to get the end offset of
 */
#define offsetofend(TYPE, MEMBER) \
	(offsetof(TYPE, MEMBER)	+ sizeof_field(TYPE, MEMBER))

struct field_desc {
    const char *type;
    size_t sz_type;
    const char *member;
    size_t sz_member;
    size_t offset;
};

#define BODY \
    FIELD(unsigned int, a) \
    FIELD(unsigned int, b) \
    FIELD(unsigned int, c) \
    FIELD(unsigned int, d) \
    FIELD(void *,       p)

#undef FIELD
#define FIELD(TYPE, MEMBER)   TYPE MEMBER;
struct fields {
    BODY
};

#undef FIELD
#define FIELD(TYPE, MEMBER)   field_ ##MEMBER,
enum field_index {
    BODY
    field_max,
};

#undef FIELD
#define FIELD(TYPE, MEMBER)   \
    {#TYPE, sizeof(TYPE), #MEMBER, \
        sizeof_field(struct fields ,MEMBER), \
        offsetof(struct fields ,MEMBER),},
static const struct field_desc descs[] =
{
    BODY
};

static void print_desc1(void)
{
    int i;
    printf("%s:%d\n", __func__, __LINE__);
    for (i = 0; i < ARRAY_SIZE(descs); i++) {
        const struct field_desc *d = &descs[i];
        printf("%d -> %15s: %lu, %5s: %lu, offset: %lu\n",
            i, d->type, d->sz_type, d->member, d->sz_member, d->offset);
    }
}

static void print_desc2(void)
{
    printf("%s:%d\n", __func__, __LINE__);
#undef FIELD
#define FIELD(TYPE, MEMBER)   \
    printf("%d -> %15s: %lu, %5s: %lu, offset: %lu\n", \
        field_ ##MEMBER, #TYPE, \
        sizeof(TYPE), #MEMBER, \
        sizeof_field(struct fields ,MEMBER), \
        offsetof(struct fields ,MEMBER));

    BODY
}


int main(void)
{
    print_desc1();
    print_desc2();

    return 0;
}
